package com.qqbot.schedule;

import com.alibaba.fastjson.JSONObject;
import com.qqbot.enums.IdentityEnum;
import com.qqbot.enums.WolfKillStatusEnum;
import com.qqbot.exception.BusinessException;
import com.qqbot.model.wolfkill.Identity;
import com.qqbot.model.wolfkill.Vote;
import com.qqbot.utils.*;
import lombok.extern.slf4j.Slf4j;
import love.forte.simbot.action.MuteSupport;
import love.forte.simbot.application.Application;
import love.forte.simbot.application.BotManagers;
import love.forte.simbot.bot.Bot;
import love.forte.simbot.definition.Group;
import love.forte.simbot.definition.GroupMember;
import org.apache.commons.lang3.StringUtils;
import org.redisson.api.RBlockingQueue;
import org.redisson.api.RDelayedQueue;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * @PackageName : com.eezi.app.schedule
 * @Author : wenwu.cai
 * @Date : 2022/4/14 6:25 下午
 * @Description : 订单异步处理：订单过期自动关闭
 **/
@Slf4j
@Component
public class AsyncService {

    @Autowired
    private RedissonUtil redissonUtil;

    @Autowired
    private Application application;

    /**
     * 狼人刀人状态结束监听
     */
    @Async
    public void wolfKillMessage() throws InterruptedException, BusinessException {
        //目标队列
        RBlockingQueue<String> blockingQueue = redissonUtil.getBlockingQueue(Constant.WOLF_QUEUE);
        //延时队列
        RDelayedQueue<String> delayedQueue = redissonUtil.getDelayedQueue(blockingQueue);
        BotManagers botManagers = application.getBotManagers();
        Bot bot = botManagers.get(0).all().get(0);
        //循环处理
        while (true) {
            blockingQueue.take();
            String statusInfo = RedisUtil.getByKey(Constant.WOLF_KILL_STATUS_KEY);
            String[] split = statusInfo.split(":");
            String groupNo = split[1];
            log.info("狼人刀人状态结束：" + statusInfo);
            Group group = bot.getGroup(SimbotUtil.getID(groupNo));
            blockingSchedule(Constant.PROPHET_QUEUE, WolfKillStatusEnum.BLACK_PROPHET.getCode(), Constant.PROPHET_TIME);
            RedisUtil.set(Constant.WOLF_KILL_STATUS_KEY, WolfKillStatusEnum.BLACK_PROPHET.getCode() + ":" + group.getId());
            group.sendAsync("预言家请睁眼");
            Map<String, JSONObject> identityMap = JSONObject.parseObject(RedisUtil.getByKey(Constant.WOLF_KILL_IDENTITY_KEY + groupNo), Map.class);
            String qq = "";
            for (String key : identityMap.keySet()) {
                Identity identity = JsonUtil.jsonToEntity(JsonUtil.toJson(identityMap.get(key)), Identity.class);
                if (identity.getIdentityCode().equals(IdentityEnum.PROPHET.getCode())) {
                    qq = identity.getQq();
                }
            }
            if (StringUtils.isNotBlank(qq)) {
                GroupMember member = group.getMember(SimbotUtil.getID(qq));
                Map<String, String> numberMap = JSONObject.parseObject(RedisUtil.getByKey(Constant.WOLF_KILL_NUMBER_KEY + groupNo), Map.class);
                String qqAndNameList = "";
                for (String key : numberMap.keySet()) {
                    String str = numberMap.get(key);
                    String[] strings = str.split(":");
                    qqAndNameList += key + " " + strings[1] + "(" + strings[0] + ")" + "\n";
                }
                member.sendBlocking("请选择要预言的玩家：\n" + qqAndNameList + "\n注：预言家有" + Constant.PROPHET_TIME + "秒的操作时长，发送“预言记录”可查看本局被预言过的玩家\n预言格式：vote/编号 如“vote/3”表示查看3号玩家的身份");
                if (!RedisUtil.judgeKeyIsExists(Constant.PROPHET_OLD_VALUE_KEY + groupNo)) {
                    RedisUtil.set(Constant.PROPHET_OLD_VALUE_KEY + groupNo, "1");
                } else {
                    RedisUtil.set(Constant.PROPHET_OLD_VALUE_KEY + groupNo, String.valueOf(Integer.valueOf(RedisUtil.getByKey(Constant.PROPHET_OLD_VALUE_KEY + groupNo)) + 1));
                }
            }

        }
    }

    /**
     * 预言家预言状态结束监听
     */
    @Async
    public void prophetMessage() throws InterruptedException, BusinessException {
        //目标队列
        RBlockingQueue<String> blockingQueue = redissonUtil.getBlockingQueue(Constant.PROPHET_QUEUE);
        //延时队列
        RDelayedQueue<String> delayedQueue = redissonUtil.getDelayedQueue(blockingQueue);
        BotManagers botManagers = application.getBotManagers();
        Bot bot = botManagers.get(0).all().get(0);
        //循环处理
        while (true) {
            blockingQueue.take();
            String statusInfo = RedisUtil.getByKey(Constant.WOLF_KILL_STATUS_KEY);
            String[] split = statusInfo.split(":");
            String groupNo = split[1];
            log.info("预言家预言状态结束：" + statusInfo);
            Group group = bot.getGroup(SimbotUtil.getID(groupNo));
            blockingSchedule(Constant.WITCH_QUEUE, WolfKillStatusEnum.BLACK_WITCH.getCode(), Constant.WITCH_TIME);
            RedisUtil.set(Constant.WOLF_KILL_STATUS_KEY, WolfKillStatusEnum.BLACK_WITCH.getCode() + ":" + group.getId());
            group.sendAsync("女巫请睁眼");
            Map<String, JSONObject> identityMap = JSONObject.parseObject(RedisUtil.getByKey(Constant.WOLF_KILL_IDENTITY_KEY + groupNo), Map.class);
            String qq = "";
            Identity identityInfo = null;
            for (String key : identityMap.keySet()) {
                Identity identity = JsonUtil.jsonToEntity(JsonUtil.toJson(identityMap.get(key)), Identity.class);
                if (identity.getIdentityCode().equals(IdentityEnum.WITCH.getCode())) {
                    qq = identity.getQq();
                    identityInfo = identity;
                }
            }
            if (StringUtils.isNotBlank(qq)) {
                GroupMember member = group.getMember(SimbotUtil.getID(qq));
                Map<String, String> numberMap = JSONObject.parseObject(RedisUtil.getByKey(Constant.WOLF_KILL_NUMBER_KEY + groupNo), Map.class);
                String qqAndNameList = "";
                for (String key : numberMap.keySet()) {
                    String str = numberMap.get(key);
                    String[] strings = str.split(":");
                    qqAndNameList += key + " " + strings[1] + "(" + strings[0] + ")" + "\n";
                }
                if (RedisUtil.judgeKeyIsExists(Constant.WOLF_VOTE_KEY + groupNo)) {
                    List<Vote> voteList = JsonUtil.jsonToList(RedisUtil.getByKey(Constant.WOLF_VOTE_KEY + groupNo), Vote.class);
                    Vote vote = voteList.stream().max(Comparator.comparing(Vote::getCount)).get();
                    member.sendBlocking("今晚死亡的是" + vote.getNumber() + "号玩家，是否要救他/她？" +
                            "\n注：解药和毒药可以一起使用\n救人命令：使用解药\n毒人命令：d/编号 比如“d/3”毒的就是3号玩家");
                }
                member.sendBlocking(qqAndNameList + "\n当前解药：" + (identityInfo.isAntidote() ? 1 : 0) + "" +
                        "\n当前毒药：" + (identityInfo.isPoison() ? 1 : 0));
            }
        }
    }

    @Async
    public synchronized void witchMessage() throws InterruptedException, BusinessException {
        //目标队列
        RBlockingQueue<String> blockingQueue = redissonUtil.getBlockingQueue(Constant.WITCH_QUEUE);
        //延时队列
        RDelayedQueue<String> delayedQueue = redissonUtil.getDelayedQueue(blockingQueue);
        BotManagers botManagers = application.getBotManagers();
        Bot bot = botManagers.get(0).all().get(0);
        //循环处理
        while (true) {
            blockingQueue.take();
            String statusInfo = RedisUtil.getByKey(Constant.WOLF_KILL_STATUS_KEY);
            String[] split = statusInfo.split(":");
            String groupNo = split[1];
            log.info("女巫状态结束：" + statusInfo);
            Group group = bot.getGroup(SimbotUtil.getID(groupNo));
            RedisUtil.set(Constant.WOLF_KILL_STATUS_KEY, WolfKillStatusEnum.WHITE.getCode() + ":" + group.getId());
            Map<String, Identity> identityMap = JSONObject.parseObject(RedisUtil.getByKey(Constant.WOLF_KILL_IDENTITY_KEY + groupNo), Map.class);
            Map<String, String> numberMap = JSONObject.parseObject(RedisUtil.getByKey(Constant.WOLF_KILL_NUMBER_KEY + groupNo), Map.class);
            List<Vote> wolfVoteList = RedisUtil.judgeKeyIsExists(Constant.WOLF_VOTE_KEY + groupNo) ? JsonUtil.jsonToList(RedisUtil.getByKey(Constant.WOLF_VOTE_KEY + groupNo), Vote.class) : Collections.EMPTY_LIST;
            Vote witchVote = RedisUtil.judgeKeyIsExists(Constant.WITCH_VOTE_KEY + groupNo) ? JsonUtil.jsonToEntity(RedisUtil.getByKey(Constant.WITCH_VOTE_KEY + groupNo), Vote.class) : null;
            Integer oldCount = Integer.valueOf(RedisUtil.getByKey(Constant.PROPHET_OLD_VALUE_KEY + groupNo));
            RedisUtil.set(Constant.PROPHET_NEW_VALUE_KEY + groupNo, String.valueOf(oldCount));
            String dieStr = "";
            String wolfDieNo = "";
            String witchDieNo = "";
            if (!CollectionUtil.isEmpty(wolfVoteList)) {
                Vote vote = wolfVoteList.stream().max(Comparator.comparing(Vote::getCount)).get();
                String number = vote.getNumber();
                wolfDieNo = number;
                dieStr += "天亮了，昨晚" + number + "号";
                RedisUtil.deleteByKey(Constant.WOLF_VOTE_KEY + groupNo);
            }
            if (!Objects.isNull(witchVote)) {
                String number = witchVote.getNumber();
                witchDieNo = number;
                dieStr += StringUtils.isNotBlank(dieStr) ? "、" + number + "号" : "天亮了，昨晚" + number + "号";
                RedisUtil.deleteByKey(Constant.WITCH_VOTE_KEY + groupNo);
            }
            String lastQq = "";
            if (StringUtils.isNotBlank(dieStr)) {
                dieStr += "玩家死亡";
                group.sendBlocking(dieStr);
                if (StringUtils.isNotBlank(wolfDieNo)) {
                    group.sendBlocking(wolfDieNo + "号玩家请留遗言");
                    String number = numberMap.get(wolfDieNo);
                    numberMap.remove(wolfDieNo);
                    Identity dieIdentity = JsonUtil.jsonToEntity(JsonUtil.toJson(identityMap.get(number.split(":")[0])), Identity.class);
                    identityMap.remove(number.split(":")[0]);
                    lastQq = dieIdentity.getQq();
                    GroupMember member = group.getMember(SimbotUtil.getID(lastQq));
                    member.unmuteBlocking();
                    if (dieIdentity.getIdentityCode().equals(IdentityEnum.HUNTER.getCode())) {
                        String qqAndNameList = "";
                        for (String key : numberMap.keySet()) {
                            String str = numberMap.get(key);
                            String[] strings = str.split(":");
                            qqAndNameList += key + " " + strings[1] + "(" + strings[0] + ")" + "\n";
                        }
                        member.sendBlocking("请选择要开枪带走的玩家：\n" + qqAndNameList + "\n注：开枪命令 vote/3 如“d/3”就是开枪带走3号玩家");
                    }
                    wait(Constant.PROPHET_TIME * 1000);
                    if (RedisUtil.judgeKeyIsExists(Constant.HUNTER_VOTE_KEY + groupNo)) {
                        String no = RedisUtil.getByKey(Constant.HUNTER_VOTE_KEY + groupNo);
                        String qq = numberMap.get(no);
                        numberMap.remove(no);
                        identityMap.remove(qq.split(":")[0]);
                        group.sendBlocking(no + "号玩家被开枪带走，没有遗言");
                    }
                }
            } else {
                group.sendBlocking("天亮了，昨晚是平安夜");
            }
            if (false) {
                //TODO 判断游戏是否结束
            }
            for (String key : numberMap.keySet()) {
                String numberInfo = numberMap.get(key);
                Identity identity = JsonUtil.jsonToEntity(JsonUtil.toJson(identityMap.get(numberInfo.split(":")[0])), Identity.class);
                group.getMember(SimbotUtil.getID(lastQq)).muteBlocking(numberMap.size(), TimeUnit.DAYS);
                lastQq = identity.getQq();
                group.getMember(SimbotUtil.getID(lastQq)).unmuteBlocking();
                group.sendBlocking(key + "号玩家请发言");
                wait(Constant.WOLF_TIME * 1000);
            }
            group.sendBlocking("自由发言环节，时间2分钟");
            group.getMembers().asStream().forEach(MuteSupport::unmuteAsync);
            wait(Constant.PROPHET_TIME * 1000);
            //TODO 投票
            group.sendBlocking("天黑请闭眼......");
            group.sendBlocking("嗷呜~~~");
            RedisUtil.set(Constant.WOLF_KILL_NUMBER_KEY + group.getId(), JsonUtil.toJson(numberMap));
            RedisUtil.set(Constant.WOLF_KILL_STATUS_KEY, WolfKillStatusEnum.BLACK_KILL.getCode() + ":" + group.getId());
            blockingSchedule(Constant.WOLF_QUEUE, WolfKillStatusEnum.BLACK_KILL.getCode(), Constant.WOLF_TIME);
        }
    }

    private void blockingSchedule(String queueName, Integer status, Long expireTime) {
        //目标阻塞队列
        RBlockingQueue<String> blockingRedPacketQueue = redissonUtil.getBlockingQueue(queueName);
        //目标延时队列
        RDelayedQueue<String> delayedRedPacketQueue = redissonUtil.getDelayedQueue(blockingRedPacketQueue);
        //将当前游戏状态存入
        delayedRedPacketQueue.offer(String.valueOf(status), expireTime, TimeUnit.SECONDS);
    }
}
